import {ITaskAgent} from "../Base/TaskPool/ITaskAgent";
import {WebRequestTask} from "./WebRequestTask";
import {StartTaskStatus} from "../Base/TaskPool/StartTaskStatus";
import {IWebRequestAgentHelper} from "./IWebRequestAgentHelper";
import {WebRequestAgentHelperCompleteEventArgs} from "./WebRequestAgentHelperCompleteEventArgs";
import {WebRequestAgentHelperErrorEventArgs} from "./WebRequestAgentHelperErrorEventArgs";
import {WebRequestTaskStatus} from "./WebRequestTaskStatus";
import {ReferencePool} from "../Base/ReferencePool/ReferencePool";

export class WebRequestAgent implements ITaskAgent<WebRequestTask>{
    get task(): WebRequestTask {
        return this._Task;
    }

    get waitTime(): number {
        return this._WaitTime;
    }

    private readonly  _Helper:IWebRequestAgentHelper;
    private _Task:WebRequestTask;
    private _WaitTime:number;

    public WebRequestAgentStart:(e:WebRequestAgent)=>void;
    public WebRequestAgentSuccess:(e:WebRequestAgent,data:number[])=>void;
    public WebRequestAgentFailure:(e:WebRequestAgent,error:string)=>void;

    constructor(webRequestAgentHelper:IWebRequestAgentHelper) {
        if (webRequestAgentHelper == null)
        {
            throw new Error("Web request agent helper is invalid.");
        }

        this._Helper = webRequestAgentHelper;
        this._Task = null;
        this._WaitTime = 0;

        this.WebRequestAgentStart = null;
        this.WebRequestAgentSuccess = null;
        this.WebRequestAgentFailure = null;
    }
    
    Initialize(): void {
        this._Helper.WebRequestAgentHelperComplete = this.OnWebRequestAgentHelperComplete;
        this._Helper.WebRequestAgentHelperError = this.OnWebRequestAgentHelperError;
    }

    private OnWebRequestAgentHelperError(sender,e:WebRequestAgentHelperErrorEventArgs) {
        this._Helper.Reset();
        this._Task.Status = WebRequestTaskStatus.Error;

        if (this.WebRequestAgentFailure != null)
        {
            this.WebRequestAgentFailure(this, e.errorMessage);
        }
        this._Task.done = true;
    }

    private OnWebRequestAgentHelperComplete(sender,e:WebRequestAgentHelperCompleteEventArgs) {
        this._Helper.Reset();
        this._Task.Status = WebRequestTaskStatus.Done;

        if (this.WebRequestAgentSuccess != null)
        {
            this.WebRequestAgentSuccess(this, e.GetWebResponseBytes());
        }

        this._Task.done = true;
    }

    Reset(): void {
        this._Helper.Reset();
        this._Task = null;
        this._WaitTime = 0;
    }

    Shutdown(): void {
        this.Reset();
        this._Helper.WebRequestAgentHelperComplete = null;
        this._Helper.WebRequestAgentHelperError = null;
    }



    Update(elapseSeconds: number, realElapseSeconds: number): void {
        if (this._Task.Status == WebRequestTaskStatus.Doing)
        {
            this._WaitTime += realElapseSeconds;
            if (this._WaitTime >= this._Task.timeout)
            {
                let webRequestAgentHelperErrorEventArgs:WebRequestAgentHelperErrorEventArgs = WebRequestAgentHelperErrorEventArgs.Create("Timeout");
                this.OnWebRequestAgentHelperError(this, webRequestAgentHelperErrorEventArgs);
                ReferencePool.Release(webRequestAgentHelperErrorEventArgs);
            }
        }
    }

    Start(task: WebRequestTask): StartTaskStatus {
        if (task == null)
        {
            throw new Error("Task is invalid.");
        }

        this._Task = task;
        this._Task.Status = WebRequestTaskStatus.Doing;

        if (this.WebRequestAgentStart != null)
        {
            this.WebRequestAgentStart(this);
        }

        let postData:number[] = this._Task.postdata;
        if (postData == null)
        {
            this._Helper.Request(this._Task.webrequesturi, this._Task.userdata);
        }
        else
        {
            this._Helper.Request(this._Task.webrequesturi, postData, this._Task.userdata);
        }
        this._WaitTime = 0;
        return StartTaskStatus.CanResume;
    }

    Task(): WebRequestTask {
        return this._Task;
    }



}